<?php
// +----------------------------------------------------------------------
// | 控制器 - ADMIN - 系统管理
// +----------------------------------------------------------------------
declare(strict_types=1);

namespace app\controller\admin\system;

use OpenApi\Annotations as OA;
use app\BaseController;
use app\model\SystemMenusModel;
use app\model\SystemRolesModel;
use app\validate\SystemRolesValidate;
use think\exception\ValidateException;
use think\Response;

/**
 * 角色管理
 *
 * Class Roles
 * @package app\controller\admin\system
 */
class Roles extends BaseController
{

    /**
     * @OA\Get(
     *   path="/api/admin/system/roles/menus",
     *   tags={"系统角色"},
     *   summary="获取可选菜单列表",
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         type="object",
     *         @OA\Property(property="total", type="integer", example="100"),
     *         @OA\Property(property="currentPage", type="integer", example="1"),
     *         @OA\Property(property="pageSize", type="integer", example="10"),
     *         @OA\Property(
     *           property="list",
     *           type="array",
     *           @OA\Items(ref="#/components/schemas/GetSystemMenus")
     *         )
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function getMenusList(): Response
    {
        $list = SystemMenusModel::queryOrder()->withSearch('status', ['status' => true])->select();
        return $this->response($list);
    }

    /**
     * @OA\Post(
     *   path="/api/admin/system/roles/page",
     *   tags={"系统角色"},
     *   summary="获取角色分页列表",
     *   @OA\RequestBody(
     *   @OA\MediaType(
     *     mediaType="content-type/json",
     *       @OA\Schema(
     *         @OA\Property(description="当前页", property="page", type="integer", example="1"),
     *         @OA\Property(description="分页数量", property="pageSize", type="integer", example="10"),
     *         @OA\Property(description="角色名检索", property="roleName", type="string", example=""),
     *         @OA\Property(description="角色标识检索", property="code", type="string", example=""),
     *         @OA\Property(description="备注检索", property="remark", type="string", example=""),
     *         @OA\Property(description="状态检索，可传入true或false", property="status", type="string", example=""),
     *         required={"page","pageSize"})
     *     )
     *   ),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         type="object",
     *         @OA\Property(property="total", type="integer", example="100"),
     *         @OA\Property(property="currentPage", type="integer", example="1"),
     *         @OA\Property(property="pageSize", type="integer", example="10"),
     *         @OA\Property(
     *           property="list",
     *           type="array",
     *           @OA\Items(ref="#/components/schemas/GetSystemRoles")
     *         )
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function getPageList(): Response
    {
        // 处理查询数据
        $search = [
            'roleName' => $this->request->post('roleName'),
            'code' => $this->request->post('code'),
            'remark' => $this->request->post('remark'),
            'status' => $this->request->post('status'),
        ];
        $list = SystemRolesModel::queryOrder()->withSearch(array_keys($search), $search)->paginate([
            'list_rows' => $this->request->post('pageSize', 10),
            'page' => $this->request->post('page', 1),
        ])->toArray();
        return $this->response([
            'list' => $list['data'],
            'total' => $list['total'],
            'currentPage' => $list['current_page'],
            'pageSize' => $list['per_page'],
        ]);
    }

    /**
     * @OA\Post(
     *   path="/api/admin/system/roles",
     *   tags={"系统角色"},
     *   summary="创建角色信息",
     *   @OA\RequestBody(
     *     required=true,
     *     @OA\JsonContent(
     *       type="object",
     *       ref="#/components/schemas/SetSystemRoles"
     *     )
     *   ),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         type="object",
     *         ref="#/components/schemas/GetSystemRoles"
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function create(): Response
    {
        $query = $this->request->post();
        try {
            // 字段验证
            validate(SystemRolesValidate::class)->scene('set')->check($query);
            // 数据新增
            $data = new SystemRolesModel();
            $data->save($query);
            // 返回新数据
            return $this->response($data->toArray());
        } catch (ValidateException $e) {
            // 验证失败 输出错误信息
            abort(200, $e->getError());
        }
    }

    /**
     * @OA\Get(
     *   path="/api/admin/system/roles/{id}",
     *   tags={"系统角色"},
     *   summary="获取角色信息",
     *   @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         type="object",
     *         ref="#/components/schemas/GetSystemRoles"
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function read(): Response
    {
        $id = $this->request->route('id');
        $data = SystemRolesModel::queryOrder()->find($id);
        if (!$data) {
            abort(404, '数据未找到');
        }
        return $this->response($data->toArray());
    }

    /**
     * @OA\Put(
     *   path="/api/admin/system/roles/{id}",
     *   tags={"系统角色"},
     *   summary="更新角色信息",
     *   @OA\Parameter(name="id", in="path", required=true,@OA\Schema(type="integer")),
     *   @OA\RequestBody(
     *     required=true,
     *     @OA\JsonContent(
     *       type="object",
     *       ref="#/components/schemas/SetSystemRoles"
     *     )
     *   ),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         type="object",
     *         ref="#/components/schemas/GetSystemRoles"
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function update(): Response
    {
        $id = $this->request->route('id');
        $query = $this->request->put();
        if (isset($query['permissions'])) {
            unset($query['permissions']);
        }
        try {
            $data = SystemRolesModel::find($id);
            if (!$data) {
                abort(404, '数据未找到');
            }
            // 字段验证
            validate(SystemRolesValidate::class)->scene('set')->check($query, SystemRolesValidate::updateRules($id));
            // 数据更新
            $data->save($query);
            // 返回新数据
            $data = SystemRolesModel::queryOrder()->find($data->id);
            return $this->response($data->toArray());
        } catch (ValidateException $e) {
            // 验证失败 输出错误信息
            abort(200, $e->getError());
        }
    }

    /**
     * @OA\Put(
     *   path="/api/admin/system/roles/{id}/permissions",
     *   tags={"系统角色"},
     *   summary="更新角色权限信息",
     *   @OA\Parameter(name="id", in="path", required=true,@OA\Schema(type="integer")),
     *   @OA\RequestBody(
     *     required=true,
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(
     *         description="菜单权限",
     *         property="menus",
     *         type="array",
     *         items={@OA\Items(type="string")},
     *         example={"System","Testing"}
     *       )
     *     )
     *   ),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         example=null
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function setPermissions(): Response
    {
        $id = $this->request->route('id');
        $query = [
            'permissions' => $this->request->put('menus', [])
        ];
        try {
            $data = SystemRolesModel::find($id);
            if (!$data) {
                abort(404, '数据未找到');
            }
            // 字段验证
            validate(SystemRolesValidate::class)->scene('permissions')->check($query);
            // 数据更新
            $data->save($query);
            return $this->response();
        } catch (ValidateException $e) {
            // 验证失败 输出错误信息
            abort(200, $e->getError());
        }
    }

    /**
     * @OA\Put(
     *   path="/api/admin/system/roles/{id}/status",
     *   tags={"系统角色"},
     *   summary="切换角色状态信息",
     *   @OA\Parameter(name="id", in="path", required=true,@OA\Schema(type="integer")),
     *   @OA\RequestBody(
     *     required=true,
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="status", type="boolean", example=true),
     *     )
     *   ),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         example=null
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function setStatus(): Response
    {
        $id = $this->request->route('id');
        $query = [
            'status' => $this->request->put('status')
        ];
        $data = SystemRolesModel::find($id);
        if (!$data) {
            abort(404, '数据未找到');
        }
        if (!$query['status'] && in_array($data->getAttr('code'), $this->request->getUserRoles())) {
            abort(200, '该角色已与您的账号绑定，无法禁用');
        }
        // 数据更新
        $data->save($query);
        return $this->response();
    }

    /**
     * @OA\Delete(
     *   path="/api/admin/system/roles/{id}",
     *   tags={"系统角色"},
     *   summary="删除角色信息",
     *   @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(
     *         property="data",
     *         example=null
     *       )
     *     )
     *   )
     * )
     * @return Response
     */
    public function delete(): Response
    {
        $id = $this->request->route('id');
        $data = SystemRolesModel::find($id);
        if (!$data) {
            abort(404, '数据未找到');
        }
        if (in_array($data->getAttr('code'), $this->request->getUserRoles())) {
            abort(200, '该角色已与您的账号绑定，无法删除');
        }
        $data->delete();
        return $this->response();
    }

    /**
     * @OA\Delete(
     *   path="/api/admin/system/roles",
     *   tags={"系统角色"},
     *   summary="批量删除角色信息",
     *   @OA\RequestBody(
     *   @OA\MediaType(
     *     mediaType="content-type/json",
     *       @OA\Schema(
     *         @OA\Property(
     *           description="指定的id",
     *           property="ids",
     *           type="array",
     *           items={@OA\Items(type="integer")},
     *           example={1, 2}
     *         ),
     *         required={"ids"})
     *     )
     *   ),
     *   security={{"bearerAuth":{}}},
     *   @OA\Response(response=401, description="未携带TOKEN或已过期"),
     *   @OA\Response(
     *     response="200",
     *     description="Success",
     *     @OA\JsonContent(
     *       type="object",
     *       @OA\Property(property="success", type="boolean", example=true),
     *       @OA\Property(property="message", type="string", example="操作成功"),
     *       @OA\Property(property="data", example=null)
     *     )
     *   )
     * )
     * @return Response
     */
    public function batchDelete(): Response
    {
        $ids = $this->request->delete('ids');
        if (!$ids || !is_array($ids)) {
            abort(404, '数据未找到');
        }
        $codes = SystemRolesModel::whereIn('id', $ids)->column('code');
        if (!empty(array_intersect($codes, $this->request->getUserRoles()))) {
            abort(200, '部分角色已与您的账号绑定，无法删除');
        }
        SystemRolesModel::destroy($ids);
        return $this->response();
    }
}
